/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Controller;

import AccountDTO.*;
import XMLManipulator.*;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.io.FileUtils;

/**
 *
 * @author Phuong Giang
 */
public class LoginController extends HttpServlet {

    private boolean found = false;
    public static AccountCollection onlineList;
    private static Properties configFile;
    private static Timer timer;

    @Override
    public void init() throws ServletException {
        try {
            // initialize online list
            onlineList = new AccountCollection();

            // initialize configFile
            InputStream inputStream = getServletContext().
                    getResourceAsStream("WEB-INF/config.properties");
            configFile = new Properties();
            configFile.load(inputStream);

            long interval = Long.parseLong(LoginController.configFile.getProperty("old-file-scan-interval"));
            long expire = Long.parseLong(LoginController.configFile.getProperty("old-file-expire-time"));

            // Giang - schedule, check delete files
            timer = new Timer();
            String dbPath = LoginController.configFile.getProperty("DBfolder");
            Collection<File> fileList = FileUtils.listFiles(new File(dbPath), new String[]{"xml"}, false);

            ExpireCheckingTask task = new ExpireCheckingTask(expire, fileList);
            timer.scheduleAtFixedRate(task, new Date(), interval);
            System.out.println("start:");

        } catch (Exception ex) {
            Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
        }
    }

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();

        String acctPath = configFile.getProperty("accounts-path");

        try {
            String action = request.getParameter("btnAction");
            // if user send login request,
            // check username and password
            if (action.equals("Sign in")) {
                //get username and password param
                String username = request.getParameter("txtUsername");
                String password = request.getParameter("txtPassword");
                found = false;
                HttpSession session = request.getSession(true);

                // get DB path


                Accounts rootElement = (Accounts) XMLDealer.Read(Accounts.class, acctPath);
                List<Account> accList = rootElement.getAccount();
                for (Account acc : accList) {
                    if (acc.getUsername().equals(username)
                            && acc.getPassword().equals(password)) {
                        found = true;
                        onlineList.add(acc);
                        session.setAttribute("USER", acc);
                        session.setAttribute("login-message", null);
                        response.sendRedirect("index.jsp");
                        break;
                    }
                }

                if (!found) {
                    session.setAttribute("USER", null);
                    // return message invalid username or password
                    session.setAttribute("login-message", "Invalid username or password!");
                    //response.getWriter().println("Invalid username or password!");
                    response.sendRedirect("login.jsp");
                }
                found = false;
            } else if (action.equals("Register")) {
                // get new user info
                String username = request.getParameter("txtUsername").trim();
                String password = request.getParameter("txtPassword");
                String displayName = request.getParameter("txtDisplayName");
                HttpSession session = request.getSession(true);

                found = false;
                // check if user existed
                Accounts rootElement = (Accounts) XMLDealer.Read(Accounts.class, acctPath);
                if (rootElement != null) {
//                    List<Account> accList = rootElement.getAccount();
                    for (Account acc : rootElement.getAccount()) {
                        if (acc.getUsername().equals(username)) {
                            found = true;
                            break;
                        }
                    }

                    // if not existed, add new user
                    if (!found) {
                        //create new account
                        Account newAcc = new Account();
                        newAcc.setUsername(username);
                        newAcc.setPassword(password);
                        newAcc.setDisplayName(displayName);

                        // add to account list
                        rootElement.getAccount().add(newAcc);

                        // write down to database
                        XMLDealer.Write(Accounts.class, acctPath, rootElement);

                        // set user in session
                        session.setAttribute("USER", newAcc);

                        // add user to online list and redirect to index
                        onlineList.add(newAcc);
                        response.sendRedirect("index.jsp");
                    }
                } else {
                    // return register-message
                    session.setAttribute("register-message", "Username already existed!");
                    response.sendRedirect("signup.jsp");
                }
            } else if (action.equals("Signout")) {
                HttpSession session = request.getSession(false);

                // remove from onlineList
                Account curAcc = (Account) session.getAttribute("USER");
                if (curAcc != null) {
                    onlineList.remove(curAcc.getUsername());
                }

                // delete session, remove USER                
                session.invalidate();
                response.sendRedirect("login.jsp");

            } else if ("usernameAvailable".equals(action)) {

                // get params
                String input = request.getParameter("username");

                Accounts accList = (Accounts) XMLDealer.Read(Accounts.class, acctPath);
                if (accList != null) {
                    for (Account acc : accList.getAccount()) {
                        if (acc.getUsername().equals(input)) {
                            out.write("{\"available\":false}");
                            return;
                        }
                    }
                }
                out.write("{\"available\":true}");
                return;
            }
        } finally {
            out.close();
        }
    }

// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}

class ExpireCheckingTask extends TimerTask {

    private long expire;
    private Collection<File> fileList;

    public ExpireCheckingTask(long expire, Collection<File> fileList) {
        this.expire = expire;
        this.fileList = fileList;
    }

    @Override
    public void run() {
        // job code here
        System.out.println(new Date());
        for (File f : fileList) {
            if (FileUtils.isFileOlder(f, new Date().getTime() - expire)) {
                try {
                    FileUtils.forceDelete(f);
                    System.out.println("deleted");
                } catch (IOException ex) {
                    Logger.getLogger(ChatController.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
                }
            }
        }
    }
}
